/**
 * Copyright (c) 2015-2019, Golly Hu 胡高 (3722711@qq.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.hg.jfsa.web.interceptor;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.jfinal.aop.Inject;
import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.kit.Kv;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.SqlPara;
import com.jfinal.plugin.ehcache.CacheKit;
import com.jfinal.plugin.ehcache.IDataLoader;

import cn.hg.jfsa.model.Column;
import cn.hg.jfsa.model.ColumnAccessLog;
import cn.hg.jfsa.web.service.api.ColumnServiceApi;
import cn.hg.jfsa.web.service.provider.ColumnServiceProvider;
import cn.hg.jfsa.web.theme.ThemeManager;

/**
 * @author Golly
 */
public class ColumnLogInterceptor implements Interceptor {

	@Inject (ColumnServiceProvider.class)
	private ColumnServiceApi columnService;

	@Override
	public void intercept (Invocation inv) {
		String requestUri = inv.getController().getRequest().getRequestURI();
		String queryString = inv.getController().getRequest().getQueryString();
		queryString = StrKit.isBlank(queryString) ? "" : "?" + queryString;
		Column column = this.getColumn(requestUri + queryString);

		if (column != null) {
			inv.getController().setAttr("COLUMN", column);
			this.updateColumnLog(column);
		}

		inv.invoke();
	}

	private Column getColumn (String requestUri) {
		Map<String, Column> columnMap = this.getColumnMap();
		return columnMap.get(requestUri);
	}

	private Map<String, Column> getColumnMap () {
		Kv para = Kv.by("theme", ThemeManager.me().getCurrentTheme().getId());
		Map<String, Column> columnMap = CacheKit.get("column", "columnMap_" + para.toString(), new IDataLoader() {

			@Override
			public Object load () {
				SqlPara sqlPara = Column.DAO.getSqlPara("module.findColumn", para);
				List<Column> list = Column.DAO.find(sqlPara);
				Map<String, Column> columnMap = new HashMap<>();

				for (Column c : list) {

					if (c.getUrlType().equals("outer")) {
						continue;
					}

					String requestUri =
						c.getUrl() + (StrKit.isBlank(c.getUrlQueryString()) ? "" : "?" + c.getUrlQueryString());

					if (columnMap.containsKey(requestUri)) {
						Column exist = columnMap.get(requestUri);

						if (c.getLayerNum() > exist.getLayerNum()) {
							columnMap.put(requestUri, c);
						}

					} else {
						columnMap.put(requestUri, c);
					}

				}

				return columnMap;
			}

		});
		return columnMap;
	}

	private Date getNowMinute () {
		Date now = new Date();
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(now);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	private void updateColumnLog (Column column) {

		synchronized (this) {
			Date now = this.getNowMinute();
			Integer exist = Db.queryInt(
				"SELECT cal.id FROM t_column_access_log AS cal WHERE cal.column_id = ? AND cal.access_time = ?",
				column.getId(), now);

			if (exist != null) {
				Db.update("UPDATE t_column_access_log SET hits = hits + 1 WHERE id = ?", exist);
			} else {
				new ColumnAccessLog()
					.setAccessTime(now)
					.setColumnId(column.getId())
					.setHits(1)
					.setTheme(column.getTheme())
					.setUrl(column.getUrl())
					.save();
			}

		}

	}

}
